#include "TimeWheel.h"
#include <func.h>

/**
 * 初始化时间轮
 */
void timewheel_init(TimeWheel* tw, int slots, int interval) {
    // 分配轮盘空间，每个槽初始化为空
    tw->wheel = (Node**)calloc(slots, sizeof(Node*));
    tw->slots = slots;
    tw->interval = interval;
    tw->current = 0;
    vector_init(&tw->vec);
    tw->last = time(NULL);
}

/**
 * 将 connfd 插入到时间轮
 */
void timewheel_add(TimeWheel* tw, int connfd) {
    Node* node;
    if ((size_t)connfd >= tw->vec.capacity || tw->vec.elements[connfd] == NULL) {
        // 文件描述符不存在
        // 创建新节点
        node = (Node*)malloc(sizeof(Node));
        node->connfd = connfd;

        vector_add(&tw->vec, connfd, node);
    } else {
        node = timewheel_remove(tw, connfd);  
    }
    
    // 头插法
    node->index = tw->current;
    node->prev = NULL;
    node->next = tw->wheel[tw->current];
    if (tw->wheel[tw->current]) {
        tw->wheel[tw->current]->prev = node;
    }
    tw->wheel[tw->current] = node;

    printf("DEBUG: add %d at %d\n", connfd, tw->current);
}

/**
 * 移除 connfd
 */
Node* timewheel_remove(TimeWheel* tw, int connfd) {
    Node* node = tw->vec.elements[connfd];
    if (node->prev) {
        node->prev->next = node->next;
    } else {
        tw->wheel[node->index] = node->next;
    }

    if (node->next) {
        node->next->prev = node->prev;
    }
    return node;
}

/**
 * 时间轮跳动 (tick)
 * 轮盘指针移动，触发超时事件
 */
void timewheel_tick(TimeWheel* tw) {

    tw->current = (tw->current + 1) % tw->slots; // 轮盘前进

    // 处理当前槽的所有超时连接
    Node* curr = tw->wheel[tw->current];
    while (curr) {
        close(curr->connfd); // 关闭连接
        printf("connfd=%d timeout, closing connection\n", curr->connfd);
        // 释放节点
        tw->vec.elements[curr->connfd] = NULL;
        Node* next = curr->next;
        free(curr);
        curr = next;
    }
    tw->wheel[tw->current] = NULL; // 清空当前槽
    tw->last = time(NULL);
}

/**
 * 释放时间轮
 */
void timewheel_destroy(TimeWheel* tw) {
    for (int i = 0; i < tw->slots; i++) {
        Node* curr = tw->wheel[i];
        while (curr) {
            Node* next = curr->next;
            free(curr);
            curr = next;
        }
    }
    free(tw->wheel);
    vector_destroy(&tw->vec);
}
